package cn.iocoder.yudao.module.mp.service.qr;

import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
import cn.iocoder.yudao.module.mp.dal.dataobject.tempqr.TempQrDO;
import cn.iocoder.yudao.module.mp.dal.mysql.tempqr.TempQrMapper;
import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.mp.enums.qrcode.MpQrSceneEnum;
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

@Service
@Slf4j
public class MpQrServiceImpl implements MpQrService{

    @Resource
    @Lazy // 延迟加载，解决循环依赖的问题
    private MpServiceFactory mpServiceFactory;

    @Resource
    @Lazy
    private MpAccountService mpAccountService;

    @Resource
    private TempQrMapper tempQrMapper;

    @Override
    public WxMpQrCodeTicket generateAccountTempQrCode(Long accountId, MpQrSceneEnum scene) {
        // 校验存在
        MpAccountDO account = mpAccountService.getAccount(accountId);
        if (account == null) {
            throw exception(ErrorCodeConstants.ACCOUNT_NOT_EXISTS);
        }
        // 生成二维码
        WxMpService mpService = mpServiceFactory.getRequiredMpService(account.getAppId());
        WxMpQrCodeTicket qrCodeTicket;
        try {
            qrCodeTicket = mpService.getQrcodeService().qrCodeCreateTmpTicket(scene.getScene(), scene.getExpireSeconds());
        } catch (WxErrorException e) {
            throw exception(ErrorCodeConstants.TEMP_QR_CODE_GENERATE_FAIL, e.getError().getErrorMsg());
        }
        tempQrMapper.insert(new TempQrDO(accountId, scene.getScene(), qrCodeTicket.getTicket()));

        return qrCodeTicket;
    }

    public void handleQrScan(String ticket, String openid) {
        TempQrDO tempQr = tempQrMapper.selectOne(Wrappers.lambdaQuery(TempQrDO.class).eq(TempQrDO::getTicket, ticket));
        if (tempQr == null) {
            throw exception(ErrorCodeConstants.TEMP_QR_NOT_EXISTS);
        }
        tempQr.setScanTime(LocalDateTime.now());
        tempQr.setScanOpenid(openid);
        tempQrMapper.updateById(tempQr);
    }

    public String getQrScanUser(String ticket) {
        TempQrDO tempQr = tempQrMapper.selectOne(Wrappers.lambdaQuery(TempQrDO.class).eq(TempQrDO::getTicket, ticket));
        if (tempQr == null) {
            throw exception(ErrorCodeConstants.TEMP_QR_NOT_EXISTS);
        }
        return tempQr.getScanOpenid();
    }

}
